home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / mindos11.zip / DEVINIT.C < prev    next >
C/C++ Source or Header  |  1991-03-22  |  10KB  |  290 lines

  1. /*  devinit.c   -- Initialize disk device attributes */
  2. /*  Copyright 1991, Steven W. Harrold - All rights reserved */
  3. /*  $Header: DEVINIT.C_V 1.4 91/03/20 08:48:19 SWH Exp $ */
  4.  
  5. #include    <stdlib.h>
  6. #include    <ctype.h>
  7. #include    <stddef.h>
  8. #include    "mfs.h"
  9. #include    "dev.h"
  10.  
  11. int Dstatus = 0 ;           /* Status returned from last dev operation */
  12.  
  13. PRIVATE struct devdata *devinitf (int drive, int sides) ;
  14. PRIVATE struct devdata *devinith (int drive) ;
  15.  
  16.  
  17. /*================================================================*/
  18. /*  This routine determines the geometry of the disk in the specified
  19. **  physical drive.
  20. **
  21. **  For floppy disks, the drives are identified by:
  22. **
  23. **      0x00 ===> the A: drive
  24. **      0x01 ===> the B: drive, and so on.
  25. **
  26. **  The physical attributes reported are a function both of the
  27. **  floppy drive AND the disk inserted in it.
  28. **
  29. **  For hard disks, the PHYSICAL drives are identified by:
  30. **
  31. **      0x80 ===> physical hard disk 0
  32. **      0x81 ===> physical hard disk 1, and so on.
  33. **
  34. **  The routine IGNORES the logical partitioning of a hard disk drive,
  35. **  as it reports the attributes of the physical device.  Make sure the
  36. **  drive identifier is NOT a function of its logical identity.  In
  37. **  particular, C: usually corresponds to physical device 0x80, but
  38. **  if D: is a second partition on the disk, it will not correspond
  39. **  to physical 0x81.
  40. */
  41.  
  42. struct devdata *devinit (drive, sides)
  43. int     drive ;     /* For floppies: 0 is A:, 1 is B:, etc */
  44.                     /* Hard drives: 0x80 is PHYSICAL disk 0, 0x81 is 1 */
  45. int     sides ;     /* 0 = determine actual value; non-0 = accept value */
  46.                     /* Use 1 when 160KB disk has a formatted 2nd side */
  47. {
  48.     if ((0xff & drive) >= 0x80)
  49.         return devinith (drive) ;
  50.     else
  51.         return devinitf (drive, sides) ;
  52.  
  53. } /* devinit() */
  54.  
  55.  
  56. /*================================================================*/
  57. /*  This routine services only floppy disk drives.  It determines,
  58. **  through trial and error, the geometry of the inserted disk.
  59. **  The actual type of drive is not determined.
  60. **
  61. **  The possibilites recognized are:
  62. **
  63. **      disk            heads   tracks  sectors
  64. **      ---------       -----   ------  -------
  65. **      160 KB 5.25"      1       40       8    rare
  66. **      320 KB 5.25"      2       40       8    less rare
  67. **      360 KB 5.25"      2       40       9    DSSD
  68. **      720 KB 5.25"      2       80       9    popular in Europe?
  69. **      1.2 MB 5.25"      2       80      15    DSDD
  70. **      720 KB 3.5"       2       80       9    low density
  71. **      1.4 MB 3.5"       2       80      18    high density
  72. */
  73.  
  74. PRIVATE struct devdata *devinitf (drive, sides)
  75. int     drive ;     /* For floppies: 0 is A:, 1 is B:, etc */
  76. int     sides ;     /* 0 = determine actual value; non-0 = accept value */
  77.                     /* Use 1 when 160KB disk has a formatted 2nd side */
  78. {
  79.     struct devdata  ddata, *dp ;
  80.     int             head, track, sector ;
  81.     int             done ;
  82.     char            buffer[SECTOR_SIZE] ;
  83.  
  84.  
  85. /*  Establish an interim data block
  86. */
  87.     dp = &ddata ;
  88.     dp->d_drive = drive ;
  89.  
  90. /*  Set the device addresses to minimum legal values.  We operate with
  91. **  these small values because we have no assurance that a disk has been
  92. **  formatted to its capacity point.  If the disk is only partially
  93. **  formatted, surely the first track, head and sector positions must
  94. **  be present.
  95. */
  96.     head = 0 ;
  97.     track = 0 ;
  98.     sector = 1 ;
  99.  
  100. /*  The disk is accessed with various known max values looking for the
  101. **  fail points.  The case of (status==NEW_MEDIA) indicates that the disk
  102. **  has been re-inserted while this test is underway, and so we have to
  103. **  start the determination all over again from the start.
  104. */
  105.     done = 0 ;
  106.     while (!done)
  107.     {
  108.  
  109. /*  Reset the controller so that we have a known hardware state.  If the
  110. **  floppy drive is not installed, the reset will fail.
  111. */
  112.         Dstatus = BIOSDISK(_DISK_RESET) ;
  113.         if (Dstatus == NEW_MEDIA) continue ;
  114.         if (Dstatus)
  115.             return NULL ;
  116.  
  117. /*  Determine number of sectors accessible on the disk.  A NO_SECTOR or a
  118. **  NO_MARKER status is expected if we reached too far.  First sector is
  119. **  number 1.  Note that we use max values for sector, but leave track
  120. **  and head at their minimum values.
  121. */
  122.         sector = 18 ;                   /* 1 of 4 possible values */
  123.         Dstatus = BIOSDISK(_DISK_VERIFY) ;
  124.         if (Dstatus) BIOSDISK(_DISK_RESET) ;
  125.         if (Dstatus == NEW_MEDIA) continue ;
  126.         if ((Dstatus == NO_MARKER) || (Dstatus == NO_SECTOR))
  127.             sector = 15 ;               /* 2nd of 4 possibilities */
  128.         else if (Dstatus)
  129.             return NULL ;
  130.  
  131.         if (sector == 15)           /* True if previous attempt failed */
  132.         {
  133.             Dstatus = BIOSDISK(_DISK_VERIFY) ;
  134.             if (Dstatus) BIOSDISK(_DISK_RESET) ;
  135.             if (Dstatus == NEW_MEDIA) continue ;
  136.             if ((Dstatus == NO_MARKER) || (Dstatus == NO_SECTOR))
  137.                 sector = 9 ;            /* 3rd of 4 possibilities */
  138.             else if (Dstatus)
  139.                 return NULL ;
  140.         }
  141.  
  142.         if (sector == 9)            /* True if previous attempt failed */
  143.         {
  144.             Dstatus = BIOSDISK(_DISK_VERIFY) ;
  145.             if (Dstatus) BIOSDISK(_DISK_RESET) ;
  146.             if (Dstatus == NEW_MEDIA) continue ;
  147.             if ((Dstatus == NO_MARKER) || (Dstatus == NO_SECTOR))
  148.                 sector = 8 ;            /* try the 4th possibility */
  149.             else if (Dstatus)
  150.                 return NULL ;
  151.         }
  152.  
  153.         if (sector == 8)            /* True if previous attempt failed */
  154.         {
  155.             Dstatus = BIOSDISK(_DISK_VERIFY) ;
  156.             if (Dstatus) BIOSDISK(_DISK_RESET) ;
  157.             if (Dstatus == NEW_MEDIA) continue ;
  158.             if (Dstatus)                 /* it's probably unformatted */
  159.                 return NULL ;
  160.         }
  161.  
  162.         dp->d_sectors = sector ;
  163.         sector = 1 ;                /* resume min value for next tests */
  164.  
  165. /*  Determine number of heads accessible on the disk.  Generally, there
  166. **  should always be two present, but a 160KB disk that is truly
  167. **  unformatted on the second side will show only 1.  Heads start with
  168. **  number 0.
  169. */
  170.         if (sides == 0)     /* test heads if no override supplied */
  171.         {
  172.             head = 1 ;
  173.             Dstatus = BIOSDISK(_DISK_VERIFY) ;
  174.             if (Dstatus) BIOSDISK(_DISK_RESET) ;
  175.             if (Dstatus == NEW_MEDIA) continue ;
  176.             if ((Dstatus == NO_MARKER) || (Dstatus == NO_SECTOR))
  177.                 head = 0 ;
  178.             else if (Dstatus)
  179.                 return NULL ;
  180.         }
  181.         else
  182.             head = sides - 1 ;      /* assumes caller said 1 or 2 */
  183.  
  184.         dp->d_heads = head + 1 ;
  185.         head = 0 ;                  /* resume min value */
  186.  
  187. /*  Determine number of tracks accessible on the disk.  A NO_MARKER
  188. **  status is expected if we attempted to reach too far.  We try here
  189. **  to avoid seeking an excessive distance past a non-existent track
  190. **  as this causes the "grinding" noise we sometimes hear in a
  191. **  floppy drive.  As the first track is number 0, a 40 track disk
  192. **  should fail with a track address of 40.
  193. **
  194. **  It seems that some floppy disk drives can seek 1 extra cylinder,
  195. **  so, as an extra precaution, a failpoint of 41 is used rather than
  196. **  the theoretical 40.  This should still avoid "head banging".
  197. */
  198.         track = 41 ;            /* "one" past the 1st max value of 39 */
  199.         Dstatus = BIOSDISK(_DISK_VERIFY) ;
  200.         if (Dstatus) BIOSDISK(_DISK_RESET) ;
  201.         if (Dstatus == NEW_MEDIA) continue ;
  202.         if ((Dstatus == NO_MARKER) || (Dstatus == NO_SECTOR))
  203.             dp->d_tracks = 40 ;     /* it is the first possibility */
  204.         else if (Dstatus)
  205.             return NULL ;
  206.         else
  207.             dp->d_tracks = 80 ;     /* must be the other possibility */
  208.  
  209. /*  When we get here, it means the disk/drive com